package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"os/exec"

	"github.com/spf13/pflag"
)

var (
	start         int
	end           int
	length        int
	feedDelimited bool
	input         string
	output        string
)

func printUsage() {
	fmt.Fprintln(os.Stderr, "Usage: selpg [ options ] [ file ]")
	fmt.Fprintln(os.Stderr, "Example: selpg -s10 -e20 ...")
}

func parseArgs() string {
	pflag.IntVarP(&start, "start", "s", -1, "Start page")
	pflag.IntVarP(&end, "end", "e", -1, "End page")
	pflag.IntVarP(&length, "length", "l", 72, "Page length")
	feedDelimitedPtr := pflag.BoolP("feed-delimited", "f", false, "Feed as delims")
	pflag.StringVarP(&output, "dest", "d", "", "Output destination")
	pflag.Parse()
	feedDelimited = *feedDelimitedPtr

	if start == -1 {
		return "Start page is required."
	}

	if end == -1 {
		return "End page is required."
	}

	if start <= 0 {
		return "Start page should be greater than 0"
	}

	if end <= 0 {
		return "End page should be greater than 0"
	}

	if end < start {
		return "End page should be greater than start page"
	}

	if pflag.NArg() >= 1 {
		input = pflag.Arg(0)
	} else {
		input = ""
	}

	return ""
}

func process(reader *bufio.Reader, writer *bufio.Writer) {
	if feedDelimited {
		page := 1
		for {
			b, err := reader.ReadByte()
			if err == io.EOF {
				break
			}
			if b == '\f' {
				page++
			}

			if page >= start && page <= end {
				writer.WriteByte(b)
			}
		}
	} else {
		line := 0
		page := 1
		scanner := bufio.NewScanner(reader)
		for scanner.Scan() {
			line++
			if line > length {
				page++
				line = 1
			}
			if page >= start && page <= end {
				writer.Write(scanner.Bytes())
				writer.WriteString("\n")
			}
		}
	}
}

func main() {
	var r = parseArgs()
	if r != "" {
		fmt.Fprintln(os.Stderr, r)
		printUsage()
		os.Exit(0)
	}

	var reader *bufio.Reader
	var writer *bufio.Writer

	if input == "" {
		reader = bufio.NewReader(os.Stdin)
	} else {
		hFile, err := os.Open(input)
		if err != nil {
			fmt.Fprintln(os.Stderr, err.Error())
		}
		reader = bufio.NewReader(hFile)
		defer hFile.Close()
	}

	if output == "" {
		writer = bufio.NewWriter(os.Stdout)
	} else {
		cmd := exec.Command("lp", fmt.Sprintf("-d%s", output))
		hFile, err := cmd.StdinPipe()
		if err != nil {
			fmt.Fprintln(os.Stderr, err.Error())
		}
		writer = bufio.NewWriter(hFile)
		defer hFile.Close()
	}
	defer writer.Flush()

	process(reader, writer)
}
